home *** CD-ROM | disk | FTP | other *** search
/ ftp.mactech.com 2010 / ftp.mactech.com.tar / ftp.mactech.com / machack / Hacks95 / Boom! '94.sit / Boom! '94 / Boom.c < prev    next >
C/C++ Source or Header  |  1995-06-24  |  16KB  |  616 lines

  1. /*
  2.     Boom!  A quick Hack to Show off PPC graphics (68k version)
  3.  
  4.     @MacHack94     bh      noEsis Software Construction 
  5. */
  6.  
  7. /*
  8.     Last Build: 
  9.                     MWerks D/R 4, 68k v1.1
  10.  
  11.     DOCS:
  12.     
  13.     This is an INIT installing a patch to _TrackGoAway for both
  14.     68k and PowerPC.  At patch execution time, if _TrackGoAway 
  15.     returns a TRUE, we create a nifty animation for the people...
  16.     
  17.     I only call the animation if one of Shift, Option, Caps-Lock,
  18.     etc.. keys are down.  That way the Finder isn't constantly
  19.     bogged down with demo booms (!)  Of course, since this is a 
  20.     patch, the effect works in any application with std Macintosh
  21.     windows.
  22.     
  23.     The animation is a bona-fide simulation in floating point.
  24.     To do the animation we use a number of offscreen GWorlds, 
  25.     and create an array of animation elements for a particular
  26.     scene. The array looks like this: 
  27.     
  28.     globals ->  ...
  29.                 gBits ->    b[0]    theta (angle)
  30.                                     speed
  31.                                     curPos
  32.                                     curDispSize
  33.                                     GWorld        -> *Gworld -> bits...
  34.  
  35.                 gBits ->    b[1]    theta (angle)
  36.                                     speed
  37.                                     curPos
  38.                                     curDispSize
  39.                                     GWorld        -> *Gworld -> bits...
  40.  
  41.                 gBits ->    b[n]    theta (angle)
  42.                                     speed
  43.                                     curPos
  44.                                     curDispSize
  45.                                     GWorld        -> *Gworld -> bits...
  46.  
  47.  
  48.     All of the simulation constants are set by compile time defines
  49.     listed below. There are currently 5 to 11 'bits' in the explosion.
  50.     The whole thing is init'd, run and cleaned up on each invocation
  51.     (except for the SndChannel in the System Heap).  You can safely
  52.     swap monitor depths between invocations, no problem...
  53.     
  54.     There were even grander plans for this 
  55.     code, but the clock ran out, so to speak, so this is what you
  56.     get.  I have found this patch to very stable, and should not 
  57.     conflict at all (who else wants possesion of _TrackGoAway ?!?)
  58.     
  59.     Spread the code and INIT far and wide, as long as all notices 
  60.     remain intact.  Any modifications, or copies of the binary built
  61.     from modifications, must be marked clearly as such.  Enjoy!
  62.     
  63.     28sep94  -bh
  64. */
  65.  
  66. //****************************************************************
  67. //                                                I N C L U D E S
  68.  
  69. #include <Types.h>
  70. #include <Memory.h>
  71. #include <A4Stuff.h>
  72. #include <SetUpA4.h>
  73. #include <Quickdraw.h>
  74. #include <QDOffscreen.h>
  75. #include <LowMem.h>
  76. #include <Errors.h>
  77. #include <GestaltEqu.h>
  78. #include <Resources.h>
  79. #include <Events.h>
  80. #include <Windows.h>
  81. #include <Sound.h>
  82. #include <Traps.h>
  83.  
  84. #include <MixedMode.h>
  85.  
  86. #include <fp.h>
  87.  
  88.  
  89. //****************************************************************
  90. //                                                C O N S T A N T S
  91. #define FALSE                false
  92. #define TRUE                true
  93. #define NIL                    0L
  94.  
  95.  
  96. //******************************
  97. //    The 68k code goes in a normal INIT resource.
  98. //    Be sure this is set to "system heap/locked".
  99.  
  100. #define kInitRezType        'INIT'
  101. #define kInitRezID            300
  102.  
  103. #define kMinSystemVersion    (0x0603)
  104.  
  105.  
  106.  
  107. //******************************
  108. // from Windows.h:
  109. // pascal Boolean TrackGoAway( WindowPtr theWindow, Point thePt)
  110. //   ONEWORDINLINE(0xA91E);
  111.  
  112. enum {
  113.  
  114.     kTrackGoAwayInfo = kCStackBased 
  115.                             | RESULT_SIZE(SIZE_CODE(sizeof(Boolean))) 
  116.                             | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(WindowPtr)))
  117.                             | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(Point)))
  118. };
  119.  
  120.  
  121. typedef pascal Boolean ( *TrackGoAwayFuncPtr ) ( WindowPtr theWindow, Point thePt );
  122. typedef UniversalProcPtr UPP;
  123.  
  124.  
  125. // ShowInit 
  126. #define kOkOldMac    128
  127. #define kOkPPC        130
  128. #define kNotOldMac    132
  129. #define kNotPPC        134
  130.  
  131. // explosion constants
  132. struct exVector {
  133.     short            theta;        // 0-360
  134.     short            speed;        // small integer
  135.     Point            pPos;        // current position
  136.     Rect            pDispR;        // current drawn size of 'bit
  137.     GWorldPtr        tPixGwP;    // map  0,0,kSrcPixSiz,kSrcPixSiz
  138. };
  139. typedef struct exVector exVector;
  140.  
  141. #define kModBits 6
  142. #define kFrameCnt 20
  143. #define kModSpeed 12
  144. #define kSrcPixSiz {0,0,3,3}
  145. #define kScratchSize 265
  146.  
  147.  
  148. //****************************************************************
  149. //                                                G L O B A L S
  150.  
  151. struct NInitGlobals
  152. {
  153.     UPP                gOrigTrackGoAway;    // old Addr
  154.     SysEnvRec        gSystemInfo;
  155.     long            gInfo;        // 1=68k,2=PPC
  156.  
  157.     Handle            gSndHandle;
  158.     SndChannelPtr    gSndChP;
  159.     exVector        *gBits;
  160.     short             gNumBits;
  161.     short             gFrameCnt;
  162.     GWorldPtr        gPad;            // working image
  163.     GWorldPtr        gSavPad;        // pristine screen copy
  164. };
  165. typedef struct NInitGlobals NInitGlobals;
  166.  
  167. NInitGlobals                *gP;
  168.  
  169.  
  170. //****************************************************************
  171. //                                                F O R W A R D S
  172.  
  173. pascal Boolean nTrackGoAway68k( WindowPtr theWindow, Point thePt);
  174. OSErr DoInitForOldMacs( void);
  175.  
  176. void PlayBoom(void);
  177. OSErr SetUpSim(void);
  178. void Animate(Point cPt);
  179. void AnimateDone(void);
  180. void ImageFrame(short frameNum, GWorldPtr dstGW, Point exPt);
  181. void PlotImage( GWorldPtr gw, short theta, short speed);
  182.  
  183. extern void ShowIconFamily(short iconId);
  184.  
  185.  
  186. //****************************************************************
  187. void main( void )
  188. {
  189.     long        oldA4, lRes;
  190.     Handle        initH = nil;        /* Handle to our own INIT resource */
  191.     OSErr        err = noErr;
  192.     
  193.     oldA4 = SetCurrentA4();            /* Get the proper value of A4 into A4 */
  194.     RememberA4();                    /* save into self-modifying code */
  195.  
  196.  
  197.     // Allocate globals struct
  198.     gP = (NInitGlobals*) NewPtrSysClear( sizeof(NInitGlobals));
  199.     if ( !gP ) {
  200.         err = memFullErr;
  201.         goto DONE;
  202.     }
  203.     
  204.      // Get minimal System Info:
  205.     err = SysEnvirons( 1, &gP->gSystemInfo );
  206.     if ( err )
  207.         goto DONE;
  208.       if ( gP->gSystemInfo.systemVersion < kMinSystemVersion ) {
  209.          err = -1;
  210.          goto DONE;
  211.      }
  212.  
  213.     // Prepare to Detach ourselves...
  214.     initH = Get1Resource( kInitRezType, kInitRezID );
  215.     if ( !initH ) {
  216.         err = resNotFound;
  217.         goto DONE;
  218.     }
  219.  
  220.     // Call Gestalt:
  221.     // Gestalt will return an err when SysArc is unimplemented
  222.     //  we know we are 68k if so  (thanks to Richard Clark)
  223.     err = Gestalt( gestaltSysArchitecture, &gP->gInfo );
  224.     if ( err) gP->gInfo = gestalt68k;
  225.  
  226.     // Load 'snd ':
  227.     // this snd is marked 'sysHeap', so it'll land in the right place,
  228.     // and we have to detach anything we want to keep around
  229.     gP->gSndHandle = GetResource ('snd ', 128);
  230.     DetachResource( gP->gSndHandle);
  231.     
  232.     { // Make a new SndChannel in the System Heap
  233.     THz savZone = GetZone();
  234.     SetZone( SystemZone());
  235.     err = SndNewChannel( &gP->gSndChP, sampledSynth, initMono, 0);
  236.     if ( err != noErr) goto DONE;
  237.     SetZone( savZone);
  238.     }
  239.     
  240.     err = DoInitForOldMacs();    // sorry, 68k setup only
  241.  
  242.  
  243.     DONE:
  244.     if ( err ) {
  245.         ShowIconFamily( kNotOldMac);
  246.         //ShowIconFamily((gP->gInfo==gestalt68k)?(kNotOldMac):(kNotPPC));
  247.         if ( gP )
  248.             DisposPtr( (Ptr)gP );
  249.     } else {
  250.         ShowIconFamily( kOkOldMac);
  251.         //ShowIconFamily((gP->gInfo==gestalt68k)?(kOkOldMac):(kOkPPC));
  252.         DetachResource( initH);    
  253.         // resource is already marked 'locked', so no HLock() here...
  254.     }
  255.     
  256.     RestoreA4( oldA4 );                    /* restore previous value of A4 */
  257. }
  258.  
  259.  
  260.  
  261. //****************************************************************
  262. //    DoInitForOldMacs
  263. //****************************************************************
  264. OSErr DoInitForOldMacs( void )
  265. {
  266.     long    oldA4;
  267.     NInitGlobals *locGPtr;
  268.  
  269.     oldA4 = SetUpA4();    
  270.     locGPtr = gP;
  271.     RestoreA4( oldA4 );    
  272.  
  273.     locGPtr->gOrigTrackGoAway = NGetTrapAddress( _TrackGoAway, ToolTrap );
  274.     NSetTrapAddress( (UPP)nTrackGoAway68k, _TrackGoAway, ToolTrap );
  275.     
  276.     return noErr;
  277. }
  278.  
  279.  
  280. //****************************************************************
  281. pascal Boolean nTrackGoAway68k( WindowPtr theWindow, Point thePt )
  282. {
  283.     Boolean        res;
  284.     long        oldA4;
  285.     GrafPtr        tPort;
  286.     Point        savPt;
  287.     TrackGoAwayFuncPtr ptr;
  288.     NInitGlobals *locGPtr;
  289.  
  290.     oldA4 = SetUpA4();        
  291.     locGPtr = gP;
  292.     
  293.     ptr = (TrackGoAwayFuncPtr)locGPtr->gOrigTrackGoAway;
  294.     savPt = thePt;
  295.     res = ( *ptr )( theWindow, thePt );
  296.     
  297.     if ( res == true) { 
  298.  
  299.         if ( *(short*)0x17A) {
  300.             THz savZone = GetZone();
  301.             SetZone( SystemZone());
  302.             
  303.             if ( SetUpSim() == noErr) {
  304.                 HideCursor();
  305.                 Animate( savPt);
  306.                 AnimateDone();
  307.                 ShowCursor();
  308.             }
  309.             SetZone( savZone);
  310.         }    
  311.     }
  312.  
  313.     RestoreA4( oldA4 );    
  314.     return res;
  315.  
  316.  
  317. //***********************************************************
  318. void AnimateDone()
  319. {
  320.     short cnt;
  321.  
  322.     DisposeGWorld( gP->gPad);
  323.     DisposeGWorld( gP->gSavPad);
  324.     for ( cnt=0;cnt<gP->gNumBits; cnt++)
  325.         DisposeGWorld( gP->gBits[cnt].tPixGwP);
  326.  
  327.     DisposPtr( (Ptr)gP->gBits);
  328. }
  329.  
  330.  
  331. //***********************
  332. #define abs(x) ((x>0)?(x):(-x))
  333.  
  334. OSErr SetUpSim(void)
  335. {
  336.     short cnt, prevT;
  337.     Rect r = kSrcPixSiz;
  338.     Rect r2;
  339.     OSErr err;
  340.  
  341.     // init scratch pads
  342.     SetRect( &r2, 0, 0, kScratchSize, kScratchSize);
  343.     err = NewGWorld( &gP->gPad,0,&r2,0,0,0);    // use 0 for best results
  344.     if ( err != noErr) return err;
  345.     err = NewGWorld( &gP->gSavPad,0,&r2,0,0,0);    // hope we have the RAM !
  346.     if ( err != noErr) return err;
  347.  
  348.     // allocate 'bits array
  349.     gP->gNumBits = abs(TickCount() % kModBits) + 5;    //ok, max+n
  350.  
  351.     gP->gBits = (exVector*)NewPtrClear( gP->gNumBits*sizeof(exVector));
  352.     for ( cnt=0;cnt<gP->gNumBits; cnt++){
  353.         gP->gBits[cnt].theta = abs((TickCount()*10+cnt) % 360);
  354.         gP->gBits[cnt].speed = abs(TickCount() % kModSpeed) + 4;
  355.         gP->gBits[cnt].pPos.h = 0;
  356.         gP->gBits[cnt].pPos.v = 0;
  357.         gP->gBits[cnt].pDispR = r;
  358.  
  359.         err = NewGWorld( &gP->gBits[cnt].tPixGwP,
  360.                     8,&r,0,0,0);
  361.         if ( err != noErr) return err;
  362.  
  363.         // now, based on speed and theta, make an image
  364.         PlotImage( gP->gBits[cnt].tPixGwP, gP->gBits[cnt].theta, gP->gBits[cnt].speed);
  365.     }
  366.     return err;
  367. }
  368.  
  369.  
  370. //**************************************************************
  371. //
  372. //    Order of Events: 
  373. //    Prestine PixMap is in gP->gSavPad, working PixMap is in gP->gPad
  374. //    For each cell of animation, copy the savPad to workPad,
  375. //    Draw all 'bits for this frame, copy gP->gPad to the screen.
  376. //
  377. //    Try This: always set the current Port to the _destination_ of
  378. //    a CopyBits() operation..    
  379.                 
  380. void Animate( Point cPt)
  381. {
  382.     GWorldPtr     savGW;
  383.     GDHandle      savGdH;
  384.     GrafPtr savP; GrafPort dPort;
  385.     Rect wR; long t;
  386.     short offX=0;
  387.     short offY=0;
  388.     Point    exPt;
  389.  
  390.     PlayBoom();
  391.  
  392.     // Create a new GrafPort on top of the current port so as to 
  393.     // disturb the graphics world as little as possible. This
  394.     // new GrafPort is the default through our copying operations.
  395.     
  396.     GetPort( &savP);
  397.     OpenPort( &dPort);
  398.     SetPort( &dPort);
  399.  
  400.     wR = gP->gPad->portRect;    
  401.  
  402.     // if the point is closer to the side of the screen than
  403.     // half the width of our buffered draw area, then adjust
  404.     // the explosion center
  405.  
  406.     if ( cPt.h > wR.right/2) {
  407.         offX = cPt.h - wR.right/2;
  408.         exPt.h = wR.right/2;
  409.     } else exPt.h = cPt.h;
  410.     if ( cPt.v > wR.bottom/2) {
  411.         offY = cPt.v - wR.bottom/2;
  412.         exPt.v = wR.bottom/2;
  413.     } else exPt.v = cPt.v;
  414.     OffsetRect( &wR, offX, offY);
  415.  
  416.     // init savMap 
  417.     GetGWorld( &savGW, &savGdH);    SetGWorld( gP->gSavPad, 0);
  418.     CopyBits(    (BitMap*)(&(dPort.portBits)),
  419.                 (BitMap*)(*(gP->gSavPad->portPixMap)), 
  420.                 &wR, &gP->gPad->portRect,
  421.                 patCopy, 0);
  422.     SetGWorld( savGW, savGdH);
  423.     
  424.     // special effects
  425.     {
  426.         #define kMax 6
  427.         Rect tR, exR; short cnt;
  428.         RGBColor tC = {0x0000,0x0000,0x0000};
  429.         PenMode( blend);    ForeColor( whiteColor);
  430.         exR.left = cPt.h - kScratchSize/2;
  431.         exR.right = cPt.h + kScratchSize/2;
  432.         exR.top = cPt.v - kScratchSize/2;
  433.         exR.bottom = cPt.v + kScratchSize/2;
  434.         for ( cnt=1; cnt<=kMax; cnt++){
  435.             tR = exR;
  436.             tC.red += 0x2A00; tC.green += 0x2A00; tC.blue += 0x2A00;
  437.             OpColor( &tC);
  438.             InsetRect( &tR, cnt*(kScratchSize/kMax), cnt*(kScratchSize/kMax));
  439.             PaintOval( &tR);
  440.             if ( gP->gInfo == gestaltPowerPC)
  441.                 Delay( 1, &t);
  442.         }
  443.         PenNormal();    ForeColor( blackColor);
  444.         if ( gP->gInfo == gestaltPowerPC)
  445.             Delay( 2, &t);
  446.         #undef kMax
  447.     }
  448.  
  449.     // animate
  450.     for (gP->gFrameCnt=0;gP->gFrameCnt<kFrameCnt;gP->gFrameCnt++) {
  451.         // copy savPad to workPad
  452.         GetGWorld( &savGW, &savGdH);    SetGWorld( gP->gPad, 0);
  453.         CopyBits(    (BitMap*)(*(gP->gSavPad->portPixMap)), 
  454.                     (BitMap*)(*(gP->gPad->portPixMap)),
  455.                     &gP->gSavPad->portRect, &gP->gPad->portRect,
  456.                     patCopy, 0);
  457.         SetGWorld( savGW, savGdH);
  458.  
  459.         ImageFrame(gP->gFrameCnt, gP->gPad, exPt);    // image 'bits
  460.  
  461.         // copy workPad to screen
  462.         CopyBits(    (BitMap*)(*(gP->gPad->portPixMap)), 
  463.                     (BitMap*)(&(dPort.portBits)),
  464.                     &gP->gPad->portRect, &wR,
  465.                     patCopy, 0);
  466.  
  467.         if ( gP->gInfo == gestaltPowerPC)
  468.             Delay( gP->gFrameCnt/4, &t);
  469.     }
  470.  
  471.     // restore screen
  472.     CopyBits(    (BitMap*)(*(gP->gSavPad->portPixMap)),
  473.                 (BitMap*)(&(dPort.portBits)), 
  474.                 &gP->gPad->portRect, &wR,
  475.                 patCopy, 0);
  476.  
  477.     SetPort( savP);
  478.     ClosePort( &dPort);
  479.     
  480.     return;
  481. }
  482.  
  483. //***********************************
  484. void ImageFrame( short frameNum, GWorldPtr dstGW, Point exPt) 
  485. {
  486.     GWorldPtr     savGW;
  487.     GDHandle      savGdH;
  488.     short    posX, posY;
  489.     short    cnt, f, tSpd;
  490.     long    t;
  491.     Rect    srcR = kSrcPixSiz;
  492.     Rect    dstR;
  493.  
  494.     // r is frameCnt * speed+frameCnt
  495.     // posX = r*cos(t)
  496.     // posY = r*sin(t)
  497.     
  498.     GetGWorld( &savGW, &savGdH);    SetGWorld( dstGW, 0);
  499.     for (f=frameNum,cnt=0;cnt<gP->gNumBits;cnt++) {
  500.         tSpd = gP->gBits[cnt].speed;
  501.         posX = (short)(f*(tSpd+cnt)) * cos(gP->gBits[cnt].theta);
  502.         posY = (short)(f*(tSpd+cnt)) * sin(gP->gBits[cnt].theta);
  503.  
  504.         dstR = gP->gBits[cnt].pDispR;
  505.  
  506.         dstR.left += exPt.h+posX;
  507.         dstR.right += exPt.h+posX;
  508.         dstR.top += exPt.v+posY;
  509.         dstR.bottom += exPt.v+posY;
  510.  
  511.         CopyBits(    (BitMap*)(*(gP->gBits[cnt].tPixGwP->portPixMap)), 
  512.                     (BitMap*)(*(dstGW->portPixMap)),
  513.                     &srcR, &dstR,
  514.                     patCopy, 0);
  515.     }
  516.     SetGWorld( savGW, savGdH);
  517. }
  518.  
  519. //**********************
  520. // Create one explosion 'bit
  521. void PlotImage( GWorldPtr gw, short theta, short speed)
  522. {
  523.     GWorldPtr     savGW;
  524.     GDHandle      savGdH;
  525.     Rect        r = kSrcPixSiz;
  526.     Point        pR1a, pR1b, pR1c;
  527.     Point        pR2, pO1, pY1a, pY1b;
  528.     RGBColor    c;
  529.  
  530.     GetGWorld( &savGW, &savGdH);
  531.     SetGWorld( gw, 0);
  532.  
  533.     c.red = 0xFFFF; c.green = 0xFFFF; c.blue = 0xFFFF;
  534.     RGBForeColor( &c);
  535.     PaintRect( &r);
  536.     PenNormal();
  537.  
  538.     if ( theta <= 22) {                                                // 22
  539.         pR1a.h=1; pR1a.v=2; pR1b.h=2; pR1b.v=1; pR1c.h=1; pR1c.v=0;
  540.         pR2.h=2; pR2.v=0; pO1.h=2; pO1.v=2; 
  541.         pY1a.h=0; pY1a.v=2; pY1b.h=0; pY1b.v=0;
  542.     } else if ( theta <= 77)  {                                        // 77
  543.         pR1a.h=2; pR1a.v=2; pR1b.h=2; pR1b.v=0; pR1c.h=0; pR1c.v=0;
  544.         pR2.h=1; pR2.v=0; pO1.h=2; pO1.v=1; 
  545.         pY1a.h=1; pY1a.v=2; pY1b.h=0; pY1b.v=1;
  546.     } else if ( theta <= 112)  {                                    // 112
  547.         pR1a.h=2; pR1a.v=1; pR1b.h=1; pR1b.v=0; pR1c.h=0; pR1c.v=1;
  548.         pR2.h=0; pR2.v=0; pO1.h=2; pO1.v=0; 
  549.         pY1a.h=2; pY1a.v=2; pY1b.h=0; pY1b.v=2;
  550.     } else if ( theta <= 157)  {                                    // 157
  551.         pR1a.h=2; pR1a.v=0; pR1b.h=0; pR1b.v=0; pR1c.h=0; pR1c.v=2;
  552.         pR2.h=0; pR2.v=1; pO1.h=1; pO1.v=0; 
  553.         pY1a.h=2; pY1a.v=1; pY1b.h=1; pY1b.v=2;
  554.     } else if ( theta <= 202)  {                                    // 202
  555.         pR1a.h=1; pR1a.v=0; pR1b.h=0; pR1b.v=1; pR1c.h=1; pR1c.v=2;
  556.         pR2.h=0; pR2.v=2; pO1.h=0; pO1.v=0; 
  557.         pY1a.h=2; pY1a.v=0; pY1b.h=2; pY1b.v=2;
  558.     } else if ( theta <= 247)  {                                    // 247
  559.         pR1a.h=0; pR1a.v=0; pR1b.h=0; pR1b.v=2; pR1c.h=2; pR1c.v=2;
  560.         pR2.h=1; pR2.v=2; pO1.h=0; pO1.v=1; 
  561.         pY1a.h=1; pY1a.v=0; pY1b.h=2; pY1b.v=1;
  562.     } else if ( theta <= 292)  {                                    // 292
  563.         pR1a.h=0; pR1a.v=1; pR1b.h=1; pR1b.v=2; pR1c.h=2; pR1c.v=1;
  564.         pR2.h=2; pR2.v=2; pO1.h=0; pO1.v=2; 
  565.         pY1a.h=0; pY1a.v=0; pY1b.h=2; pY1b.v=0;
  566.     } else if ( theta <= 337)  {                                    // 337
  567.         pR1a.h=0; pR1a.v=2; pR1b.h=2; pR1b.v=2; pR1c.h=2; pR1c.v=0;
  568.         pR2.h=2; pR2.v=1; pO1.h=1; pO1.v=2; 
  569.         pY1a.h=0; pY1a.v=1; pY1b.h=1; pY1b.v=0;
  570.     } else {                                                        // +-22
  571.         pR1a.h=1; pR1a.v=2; pR1b.h=2; pR1b.v=1; pR1c.h=1; pR1c.v=0;
  572.         pR2.h=2; pR2.v=0; pO1.h=2; pO1.v=2; 
  573.         pY1a.h=0; pY1a.v=2; pY1b.h=0; pY1b.v=0;
  574.     }
  575.  
  576.     // NOTE: assumes 'bit pix size of 3x3 !!
  577.  
  578.     c.red = 0xFFFF; c.green = 0x2000; c.blue = 0;        // r1
  579.     RGBForeColor( &c);
  580.     MoveTo( pR1a.h,pR1a.v);    Line(0,0);
  581.     MoveTo( pR1b.h,pR1c.v);    Line(0,0);
  582.     MoveTo( pR1c.h,pR1c.v);    Line(0,0);
  583.  
  584.     c.red = 0xBAC7; c.green = 0; c.blue = 0;            // r2
  585.     RGBForeColor( &c);
  586.     MoveTo( pR2.h,pR2.v);    Line(0,0);
  587.     MoveTo( pO1.h,pO1.v);    Line(0,0);
  588.  
  589.     c.red = 0xFFFF; c.green = 0xCCC8; c.blue = 0;        // o2 (always center)
  590.     RGBForeColor( &c);
  591.     MoveTo( 1,1);    Line(0,0);
  592.  
  593.     c.red = 0xFFFF; c.green = 0xFFFF; c.blue = 0;        // y
  594.     RGBForeColor( &c);
  595.     MoveTo( pY1a.h,pY1a.v);    Line(0,0);
  596.     MoveTo( pY1b.h,pY1b.v);    Line(0,0);
  597.  
  598.     SetGWorld( savGW, savGdH);
  599.     return;
  600. }
  601.  
  602.  
  603. //***********************************************************
  604. void PlayBoom()
  605. {
  606.     OSErr err;
  607.  
  608.     if ( gP->gSndHandle != nil ) 
  609.         err = SndPlay( gP->gSndChP, (SndListHandle)gP->gSndHandle, true);
  610. }
  611.  
  612.  
  613. //***********************************************************************************
  614. //                                                        E N D   O F   L I S T I N G
  615.